1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 package com.touchgraph.graphlayout;
51
52 import java.awt.*;
53 import java.util.*;
54
55 /*** Node.
56 *
57 * @author Alexander Shapiro
58 * @author Murray Altheim (2001-11-06; added support for round rects and alternate Node colors)
59 * @version 1.21 $Id: Node.java,v 1.1.1.1 2004/02/06 08:44:05 keesj Exp $
60 */
61 public class Node {
62
63 /*** This Node's type is a Rectangle. */
64 public final static int TYPE_RECTANGLE = 1;
65
66 /*** This Node's type is a Round Rectangle. */
67 public final static int TYPE_ROUNDRECT = 2;
68
69 /*** This Node's type is an Ellipse. */
70 public final static int TYPE_ELLIPSE = 3;
71
72 /*** This Node's type is a Circle. */
73 public final static int TYPE_CIRCLE = 4;
74
75 public static final Font SMALL_TAG_FONT = new Font("Courier",Font.PLAIN,9);
76
77
78 public static Color BACK_FIXED_COLOR = Color.red;
79 public static Color BACK_SELECT_COLOR = new Color(255, 224, 0);
80 public static Color BACK_DEFAULT_COLOR = new Color(208, 96, 0);
81 public static Color BACK_HILIGHT_COLOR = Color.decode("#ffb200");
82
83 public static Color BORDER_DRAG_COLOR = Color.black;
84 public static Color BORDER_MOUSE_OVER_COLOR = new Color(160,160,160);
85 public static Color BORDER_INACTIVE_COLOR = Color.white;
86
87 public static Color TEXT_COLOR = Color.white;
88
89 public static Font TEXT_FONT = new Font("Courier",Font.PLAIN,12);
90
91 public static int DEFAULT_TYPE = 1;
92
93 /*** an int indicating the Node type.
94 * @see TYPE_RECTANGLE
95 * @see TYPE_ROUNDRECT
96 * @see TYPE_ELLIPSE
97 */
98 protected int typ = TYPE_RECTANGLE;
99 private String id;
100
101 public double drawx;
102 public double drawy;
103
104 protected FontMetrics fontMetrics;
105 protected Font font;
106
107 protected String lbl;
108 protected Color backColor = BACK_DEFAULT_COLOR;
109 protected Color textColor = TEXT_COLOR;
110
111 public double x;
112 public double y;
113
114 protected double dx;
115 protected double dy;
116
117 protected boolean fixed;
118 protected int repulsion;
119
120 public boolean justMadeLocal = false;
121 public boolean markedForRemoval = false;
122
123 public int visibleEdgeCnt;
124 protected boolean visible;
125
126 private Vector edges;
127
128
129
130
131 /*** Minimal constructor which will generate an ID value from Java's Date class.
132 * Defaults will be used for type and color. The label will be taken from the ID value.
133 */
134 public Node()
135 {
136 initialize(null);
137 lbl = id;
138 }
139
140 /*** Constructor with the required ID <tt>id</tt>, using defaults
141 * for type (rectangle), color (a static variable from TGPanel).
142 * The Node's label will be taken from the ID value.
143 */
144 public Node( String id )
145 {
146 initialize(id);
147 lbl = id;
148 }
149
150 /*** Constructor with Strings for ID <tt>id</tt> and <tt>label</tt>, using defaults
151 * for type (rectangle) and color (a static variable from TGPanel).
152 * If the label is null, it will be taken from the ID value.
153 */
154 public Node( String id, String label )
155 {
156 initialize(id);
157 if ( label == null ) lbl = id;
158 else lbl = label;
159 }
160
161 /*** Constructor with a String ID <tt>id</tt>, an int <tt>type</tt>, Background Color <tt>bgColor</tt>,
162 * and a String <tt>label</tt>. If the label is null, it will be taken from the ID value.
163 * @see TYPE_RECTANGLE
164 * @see TYPE_ROUNDRECT
165 */
166 public Node( String id, int type, Color color, String label )
167 {
168 initialize(id);
169 typ = type;
170 backColor = color;
171 if ( label == null ) lbl = id;
172 else lbl = label;
173 }
174
175 private void initialize( String identifier ) {
176 this.id = identifier;
177 edges = new Vector();
178 x = Math.random()*2-1;
179 y = Math.random()*2-1;
180 repulsion = 100;
181 font = TEXT_FONT;
182 fixed = false;
183 typ = DEFAULT_TYPE;
184 visibleEdgeCnt=0;
185 visible = false;
186 }
187
188
189
190
191 public static void setNodeBackFixedColor( Color color ) { BACK_FIXED_COLOR = color; }
192 public static void setNodeBackSelectColor( Color color ) { BACK_SELECT_COLOR = color; }
193 public static void setNodeBackDefaultColor( Color color ) { BACK_DEFAULT_COLOR = color; }
194 public static void setNodeBackHilightColor( Color color ) { BACK_HILIGHT_COLOR = color; }
195 public static void setNodeBorderDragColor( Color color ) { BORDER_DRAG_COLOR = color; }
196 public static void setNodeBorderMouseOverColor( Color color ) { BORDER_MOUSE_OVER_COLOR = color; }
197 public static void setNodeBorderInactiveColor( Color color ) { BORDER_INACTIVE_COLOR = color; }
198 public static void setNodeTextColor( Color color ) { TEXT_COLOR = color; }
199 public static void setNodeTextFont( Font font ) { TEXT_FONT = font; }
200 public static void setNodeType( int type ) { DEFAULT_TYPE = type; }
201
202 /*** Set the ID of this Node to the String <tt>id</tt>.
203 */
204 public void setID( String id ) {
205 this.id = id;
206 }
207
208 /*** Return the ID of this Node as a String.
209 */
210 public String getID() {
211 return id;
212 }
213
214 /*** Set the location of this Node provided the Point <tt>p</tt>.
215 */
216 public void setLocation( Point p ) {
217 this.x = p.x;
218 this.y = p.y;
219 }
220
221
222 /*** Return the location of this Node as a Point.
223 */
224 public Point getLocation() {
225 return new Point((int)x,(int)y);
226 }
227
228 /*** Set the visibility of this Node to the boolean <tt>v</tt>.
229 */
230 public void setVisible( boolean v) {
231 visible = v;
232 }
233
234 /*** Return the visibility of this Node as a boolean.
235 */
236 public boolean isVisible() {
237 return visible;
238 }
239
240 /*** Set the type of this Node to the int <tt>type</tt>.
241 * @see TYPE_RECTANGLE
242 * @see TYPE_ROUNDRECT
243 * @see TYPE_ELLIPSE
244 * @see TYPE_CIRCLE
245 */
246
247 public void setType( int type ) {
248 typ = type;
249 }
250
251 /*** Return the type of this Node as an int.
252 * @see TYPE_RECTANGLE
253 * @see TYPE_ROUNDRECT
254 * @see TYPE_ELLIPSE
255 * @see TYPE_CIRCLE
256 */
257 public int getType() {
258 return typ;
259 }
260
261 /*** Set the font of this Node to the Font <tt>font</tt>. */
262 public void setFont( Font font ) {
263 this.font = font;
264 }
265
266 /*** Returns the font of this Node as a Font*/
267 public Font getFont() {
268 return font;
269 }
270
271 /*** Set the background color of this Node to the Color <tt>bgColor</tt>. */
272 public void setBackColor( Color bgColor ) {
273 backColor = bgColor;
274 }
275
276 /*** Return the background color of this Node as a Color.
277 */
278 public Color getBackColor() {
279 return backColor;
280 }
281
282 /*** Set the text color of this Node to the Color <tt>txtColor</tt>. */
283 public void setTextColor( Color txtColor ) {
284 textColor = txtColor;
285 }
286
287
288 /*** Return the text color of this Node as a Color.
289 */
290 public Color getTextColor() {
291 return textColor;
292 }
293
294
295 /*** Set the label of this Node to the String <tt>label</tt>. */
296 public void setLabel( String label ) {
297 lbl = label;
298 }
299
300 /*** Return the label of this Node as a String.
301 */
302 public String getLabel() {
303 return lbl;
304 }
305
306 /*** Set the fixed status of this Node to the boolean <tt>fixed</tt>. */
307 public void setFixed( boolean fixed ) {
308 this.fixed = fixed;
309 }
310
311
312 /*** Returns true if this Node is fixed (in place).
313 */
314 public boolean getFixed() {
315 return fixed;
316 }
317
318
319
320 /*** Return the number of Edges in the cumulative Vector.
321 * @deprecated this method has been replaced by the <tt>edgeCount()</tt> method.
322 */
323 public int edgeNum() {
324 return edges.size();
325 }
326
327 /*** Return the number of Edges in the cumulative Vector. */
328 public int edgeCount() {
329 return edges.size();
330 }
331
332 /*** Return an iterator over the Edges in the cumulative Vector, null if it is empty. */
333 public Iterator getEdges() {
334 if ( edges.size() == 0 ) return null;
335 else return edges.iterator();
336 }
337
338 /*** Returns the local Edge count. */
339 public int visibleEdgeCount() {
340 return visibleEdgeCnt;
341 }
342
343 /*** Return the Edge at int <tt>index</tt>. */
344 public Edge edgeAt( int index ) {
345 return (Edge)edges.elementAt(index);
346 }
347
348 /*** Add the Edge <tt>edge</tt> to the graph. */
349 public void addEdge( Edge edge ) {
350 if ( edge == null ) return;
351 edges.addElement(edge);
352 }
353
354 /*** Remove the Edge <tt>edge</tt> from the graph. */
355 public void removeEdge( Edge edge ) {
356 edges.removeElement(edge);
357 }
358
359 /*** Return the width of this Node. */
360 public int getWidth() {
361 if ( fontMetrics != null && lbl != null ) {
362 return fontMetrics.stringWidth(lbl) + 12;
363 } else {
364 return 10;
365 }
366 }
367
368 /*** Return the height of this Node. */
369 public int getHeight() {
370 if ( fontMetrics != null ) {
371 return fontMetrics.getHeight() + 6;
372 } else {
373 return 6;
374 }
375 }
376
377 /*** Returns true if this Node intersects Dimension <tt>d</tt>. */
378 public boolean intersects( Dimension d ) {
379 return ( drawx > 0 && drawx < d.width && drawy>0 && drawy < d.height );
380 }
381
382 /*** Returns true if this Node contains the Point <tt>px,py</tt>. */
383 public boolean containsPoint( double px, double py ) {
384 return (( px > drawx-getWidth()/2) && ( px < drawx+getWidth()/2)
385 && ( py > drawy-getHeight()/2) && ( py < drawy+getHeight()/2));
386 }
387
388 /*** Returns true if this Node contains the Point <tt>p</tt>. */
389 public boolean containsPoint( Point p ) {
390 return (( p.x > drawx-getWidth()/2) && ( p.x < drawx+getWidth()/2)
391 && ( p.y > drawy-getHeight()/2) && ( p.y < drawy+getHeight()/2));
392 }
393
394 /*** Paints the Node. */
395 public void paint( Graphics g, TGPanel tgPanel ) {
396 if (!intersects(tgPanel.getSize()) ) return;
397 paintNodeBody(g, tgPanel);
398
399 if ( visibleEdgeCount()<edgeCount() ) {
400 int ix = (int)drawx;
401 int iy = (int)drawy;
402 int h = getHeight();
403 int w = getWidth();
404 int tagX = ix+(w-7)/2-2+w%2;
405 int tagY = iy-h/2-2;
406 char character;
407 int hiddenEdgeCount = edgeCount()-visibleEdgeCount();
408 character = (hiddenEdgeCount<9) ? (char) ('0' + hiddenEdgeCount) : '*';
409 paintSmallTag(g, tgPanel, tagX, tagY, Color.red, Color.white, character);
410 }
411 }
412
413 public Color getPaintBorderColor(TGPanel tgPanel) {
414 if (this == tgPanel.getDragNode()) return BORDER_DRAG_COLOR;
415 else if (this == tgPanel.getMouseOverN()) return BORDER_MOUSE_OVER_COLOR;
416 else return BORDER_INACTIVE_COLOR;
417 }
418
419 public Color getPaintBackColor(TGPanel tgPanel) {
420 if ( this == tgPanel.getSelect() ) {
421 return BACK_SELECT_COLOR;
422 } else {
423 if (fixed) return BACK_FIXED_COLOR;
424 if (markedForRemoval) return new Color(100,60,40);
425 if (justMadeLocal) return new Color(255,220,200);
426 return backColor;
427 }
428 }
429
430 public Color getPaintTextColor(TGPanel tgPanel) {
431 return textColor;
432 }
433
434 /*** Paints the background of the node, along with its label */
435 public void paintNodeBody( Graphics g, TGPanel tgPanel) {
436 g.setFont(font);
437 fontMetrics = g.getFontMetrics();
438
439 int ix = (int)drawx;
440 int iy = (int)drawy;
441 int h = getHeight();
442 int w = getWidth();
443 int r = h/2+1;
444
445 Color borderCol = getPaintBorderColor(tgPanel);
446 g.setColor(borderCol);
447
448 if ( typ == TYPE_ROUNDRECT ) {
449 g.fillRoundRect(ix - w/2, iy - h / 2, w, h, r, r);
450 } else if ( typ == TYPE_ELLIPSE ) {
451 g.fillOval(ix - w/2, iy - h / 2, w, h );
452 } else if ( typ == TYPE_CIRCLE ) {
453 g.fillOval(ix - w/2, iy - w / 2, w, w );
454 } else {
455 g.fillRect(ix - w/2, iy - h / 2, w, h);
456 }
457
458 Color backCol = getPaintBackColor(tgPanel);
459 g.setColor(backCol);
460
461 if ( typ == TYPE_ROUNDRECT ) {
462 g.fillRoundRect(ix - w/2+2, iy - h / 2+2, w-4, h-4, r, r );
463 } else if ( typ == TYPE_ELLIPSE ) {
464 g.fillOval(ix - w/2+2, iy - h / 2+2, w-4, h-4 );
465 } else if ( typ == TYPE_CIRCLE ) {
466 g.fillOval(ix - w/2+2, iy - w / 2+2, w-4, w-4 );
467 } else {
468 g.fillRect(ix - w/2+2, iy - h / 2+2, w-4, h-4);
469 }
470
471 Color textCol = getPaintTextColor(tgPanel);
472 g.setColor(textCol);
473 g.drawString(lbl, ix - fontMetrics.stringWidth(lbl)/2, iy + fontMetrics.getDescent() +1);
474 }
475
476 /*** Paints a tag with containing a character in a small font. */
477 public void paintSmallTag(Graphics g, TGPanel tgPanel, int tagX, int tagY,
478 Color backCol, Color textCol, char character) {
479 g.setColor(backCol);
480 g.fillRect(tagX, tagY, 8, 8);
481 g.setColor(textCol);
482 g.setFont(SMALL_TAG_FONT);
483 g.drawString(""+character, tagX+2, tagY+7);
484 }
485
486 }